#ifndef __POSTMON_H__
#define __POSTMON_H__

#include <windows.h>
#include "postmon.h"
#include "statbar.h" 
#include "resource.h"

#ifndef INTERNET_MAX_SCHEME_LENGTH
#define INTERNET_MAX_SCHEME_LENGTH      32          // longest protocol name length
#endif

#define EDIT_BOX_LIMIT 0x7FFF    //  The Edit box limit
#ifdef _DEBUG
#define ODS(x) OutputDebugString(x)
#else
#define ODS(x)
#endif

//---------------------------------------------------------------------------
// String helpers
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// ANSI/WIDE String helpers.
//---------------------------------------------------------------------------
// Given and ANSI String, copy it into a wide buffer.
// NOTE:  Be careful about scoping when using this macro!  A TempBuffer
//        variable of the appropriate size is created at the beginning of the
//        macro.  That variable is automatically destroyed when it goes out
//        of scope.  That means you may need to use braces around the block of 
//        code which uses it.  It also means the macro can be used only once 
//        within any given block.
//
// How to use the following two macros:
//
//  ...
//  LPSTR pszA;
//  pszA = MyGetAnsiStringRoutine();
//  MAKE_WIDEPTR_FROMANSI(pwsz, pszA);
//  MyUseWideStringRoutine(pwsz);
//  ...
//
// Similarily for MAKE_ANSIPTR_FROMWIDE().  Note that the first param does
// not have to be declared, and no clean up must be done.
//---------------------------------------------------------------------------
#define MAKE_WIDEPTR_FROMANSI(ptrname, ansistr) \
    long __l##ptrname = (lstrlen(ansistr) + 1) * sizeof(WCHAR); \
    TempBuffer __TempBuffer##ptrname(__l##ptrname); \
    MultiByteToWideChar(CP_ACP, 0, ansistr, -1, (LPWSTR)__TempBuffer##ptrname.GetBuffer(), __l##ptrname); \
    LPWSTR ptrname = (LPWSTR)__TempBuffer##ptrname.GetBuffer()

#define MAKE_ANSIPTR_FROMWIDE(ptrname, widestr) \
    long __l##ptrname = (lstrlenW(widestr) + 1) * sizeof(char); \
    TempBuffer __TempBuffer##ptrname(__l##ptrname); \
    WideCharToMultiByte(CP_ACP, 0, widestr, -1, (LPSTR)__TempBuffer##ptrname.GetBuffer(), __l##ptrname, NULL, NULL); \
    LPSTR ptrname = (LPSTR)__TempBuffer##ptrname.GetBuffer()

#define FreeBSTR(wsz){				\
	if (wsz)					\
	{									\
		SysFreeString(wsz);	\
	} }


//---------------------------------------------------------------------------
// TempBuffer class
//---------------------------------------------------------------------------
class TempBuffer
{
#define MAX_TEMP_BUFFER 120
public:
	TempBuffer(ULONG cb)
			{
				m_fAlloc = (cb > MAX_TEMP_BUFFER);
				if (m_fAlloc)
				{
					m_pbBuf = new char[cb];
				}
				else
				{
					m_pbBuf = &m_szBufT;
				}
			}
	~TempBuffer() { if (m_pbBuf && m_fAlloc) delete m_pbBuf; }
	LPVOID GetBuffer(void) { return m_pbBuf; }

private:
	LPVOID m_pbBuf;
	char m_szBufT[MAX_TEMP_BUFFER];  // We'll use this temp buffer for small cases.
	int m_fAlloc;
};

class CApp;

class CStatus
{
public:
	CStatus(CApp* pApp, CStatusBar* pStatusBar, HWND hwndResponse, HWND hwndProgressBar) 
		: m_pApp(pApp), m_pStatusBar(pStatusBar), m_hwndResponse(hwndResponse), m_hwndProgressBar(hwndProgressBar) { ; }
	~CStatus() { ; }
	static HRESULT Create(CApp* pApp, CStatusBar* pStatusBar, HWND hwndResponse, HWND hwndProgressBar, CStatus** ppStatus);
	HRESULT Init();

	void SetStatusText(LPCTSTR szText, int iPart = 0) { if (m_pStatusBar) m_pStatusBar->SetText(szText, iPart); }
	void UpdateProgress(ULONG cProgress, ULONG maxProgress)
	{
		// Set the range and increment of the progress bar. 
		SendMessage(m_hwndProgressBar, PBM_SETRANGE, 0, 100); 
        SendMessage(m_hwndProgressBar, PBM_SETPOS, (WPARAM) (maxProgress ? cProgress * 100 / maxProgress : 0), 0);
	}

	void OnDownloadComplete();
	void Close() { m_pApp = NULL; } // Zombie

	HRESULT AppendResponse(LPCTSTR szResponse);

protected:
	CStatusBar* m_pStatusBar;
	HWND m_hwndResponse;
	HWND m_hwndProgressBar;
	CApp* m_pApp;
};

class CDownload {
  public:
    HRESULT DoUpload(CStatus* pStatus, LPOLESTR wszUrl, LPCTSTR szData, BINDVERB dwAction);

	CDownload() : m_pmk(NULL), m_pbc(NULL), m_pbsc(NULL) { ; }
    ~CDownload();
	static HRESULT Create(CDownload** ppDownload);
	HRESULT Init(/*LPCTSTR szUrl*/);

  private:
    LPMONIKER				m_pmk;
    LPBINDCTX				m_pbc;
    LPBINDSTATUSCALLBACK	m_pbsc;
};

class CApp
{
public:
	static HRESULT Create(HINSTANCE hinst, LPCTSTR szCmdLine, CApp** ppApp);
	HRESULT Init();
	int Run();

	CApp(HINSTANCE hinst, LPCTSTR szCmdLine) : m_fOleInitialized(FALSE), 
			m_pDownload(NULL), m_hinst(hinst), m_szCmdLine(szCmdLine), 
			m_fSubmitRawData(FALSE), m_hwndFrame(NULL), m_pStatus(NULL)
			{ ; }
	~CApp();

	HRESULT OnInitDialog(HWND hwndDlg);

	HRESULT OnSubmit();
	BOOL ShouldSubmitRawData() { return m_fSubmitRawData; }
	void SubmitRawData(BOOL fRaw) 
	{ 
		m_fSubmitRawData = fRaw; 
		SendMessage(GetDlgItem(m_hwndFrame, IDC_RAW), BM_SETCHECK, (WPARAM)(fRaw ? BST_CHECKED : BST_UNCHECKED), 0); 
		EnableWindow(GetDlgItem(m_hwndFrame, IDC_FIRSTNAME), !fRaw); 
		EnableWindow(GetDlgItem(m_hwndFrame, IDC_FLAVOR), !fRaw);
		EnableWindow(GetDlgItem(m_hwndFrame, IDC_POSTDATA), fRaw);
	}

	void EnableUI()
	{
		if (m_hwndFrame)
		{
			EnableWindow(GetDlgItem(m_hwndFrame, IDOK), TRUE);
			EnableWindow(GetDlgItem(m_hwndFrame, IDC_URL), TRUE);
		}
	}

	CStatus* m_pStatus;
	CStatusBar m_StatusBar;

protected:
	CDownload* m_pDownload;
	HINSTANCE m_hinst;
	LPCTSTR m_szCmdLine;
	BOOL m_fOleInitialized;
	HWND m_hwndFrame;
	BOOL m_fSubmitRawData;
};

HRESULT BuildQueryString(HWND hwndFirstName, HWND hwndFlavor, LPSTR szData, BINDVERB dwAction);
HRESULT CombineUrlWithQueryString(LPTSTR szUrl, DWORD dwUrl, LPTSTR szData);
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);

#endif // __POSTMON_H__